package com.kexio.user.dto;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;

import org.springframework.util.StringUtils;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.kexio.common.page.PageQuery;

import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;

/**
 * 权限统一DTO
 * 
 * 用于权限管理的统一数据传输，支持创建、更新、响应、分页查询等场景。
 * 继承PageQuery支持分页，采用统一DTO设计减少类型转换复杂度。
 * 
 * @author Kexio Team
 * @since 1.0.0
 */
public class PermissionDTO extends PageQuery implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    // ==================== 基础字段 ====================
    
    /**
     * 权限ID（响应时使用，创建时忽略）
     */
    private String permissionId;
    
    /**
     * 租户ID
     */
    private String tenantId;
    
    /**
     * 权限编码（在租户内唯一，如：system:user:list）
     */
    @NotBlank(message = "权限编码不能为空")
    @Size(min = 3, max = 100, message = "权限编码长度必须在3-100个字符之间")
    @Pattern(regexp = "^[a-zA-Z][a-zA-Z0-9_:-]*$", message = "权限编码格式不正确，必须以字母开头，只能包含字母、数字、下划线、冒号和短横线")
    private String permissionCode;
    
    /**
     * 权限名称
     */
    @NotBlank(message = "权限名称不能为空")
    @Size(min = 2, max = 50, message = "权限名称长度必须在2-50个字符之间")
    private String permissionName;
    
    /**
     * 权限类型：OP-操作权限，RESOURCE-资源权限，API-接口权限
     */
    @NotBlank(message = "权限类型不能为空")
    @Pattern(regexp = "^(OP|RESOURCE|API)$", message = "权限类型必须是 OP、RESOURCE 或 API")
    private String permissionType;
    
    /**
     * 权限描述
     */
    @Size(max = 200, message = "权限描述长度不能超过200个字符")
    private String description;
    
    // ==================== 层级字段 ====================
    
    /**
     * 父权限ID（用于权限层级）
     */
    private String parentPermissionId;
    
    /**
     * 权限路径（层级路径，如：/system/user）
     */
    @Size(max = 200, message = "权限路径长度不能超过200个字符")
    @Pattern(regexp = "^(/[a-zA-Z0-9_-]+)*/?$", message = "权限路径格式不正确")
    private String permissionPath;
    
    // ==================== 状态字段 ====================
    
    /**
     * 状态：1-启用，0-禁用
     */
    @NotNull(message = "状态不能为空")
    @Min(value = 0, message = "状态值最小为0")
    @Max(value = 1, message = "状态值最大为1")
    private Integer status;
    
    /**
     * 排序号
     */
    private Integer orderNo;
    
    /**
     * 关联菜单ID（新架构中权限直接关联菜单）
     */
    private String menuId;
    
    // ==================== 审计字段 ====================
    
    /**
     * 创建人
     */
    private String createBy;
    
    /**
     * 创建时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    
    /**
     * 更新人
     */
    private String updateBy;
    
    /**
     * 更新时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
    
    // ==================== 关联字段（响应时使用） ====================
    
    /**
     * 父权限信息（响应时可能包含）
     */
    private PermissionDTO parentPermission;
    
    /**
     * 子权限列表（响应时可能包含）
     */
    private List<PermissionDTO> childPermissions;
    
    /**
     * 关联的角色数量（统计字段）
     */
    private Integer roleCount;
    
    /**
     * 关联的用户数量（统计字段）
     */
    private Integer userCount;
    
    // ==================== 构造函数 ====================
    
    public PermissionDTO() {
    }
    
    // ==================== Getter/Setter ====================
    
    public String getPermissionId() {
        return permissionId;
    }
    
    public void setPermissionId(String permissionId) {
        this.permissionId = permissionId;
    }
    
    public String getTenantId() {
        return tenantId;
    }
    
    public void setTenantId(String tenantId) {
        this.tenantId = tenantId;
    }
    
    public String getPermissionCode() {
        return permissionCode;
    }
    
    public void setPermissionCode(String permissionCode) {
        this.permissionCode = permissionCode;
    }
    
    public String getPermissionName() {
        return permissionName;
    }
    
    public void setPermissionName(String permissionName) {
        this.permissionName = permissionName;
    }
    
    public String getPermissionType() {
        return permissionType;
    }
    
    public void setPermissionType(String permissionType) {
        this.permissionType = permissionType;
    }
    
    public String getDescription() {
        return description;
    }
    
    public void setDescription(String description) {
        this.description = description;
    }
    
    public String getParentPermissionId() {
        return parentPermissionId;
    }
    
    public void setParentPermissionId(String parentPermissionId) {
        this.parentPermissionId = parentPermissionId;
    }
    
    public String getPermissionPath() {
        return permissionPath;
    }
    
    public void setPermissionPath(String permissionPath) {
        this.permissionPath = permissionPath;
    }
    
    public Integer getStatus() {
        return status;
    }
    
    public void setStatus(Integer status) {
        this.status = status;
    }
    
    public Integer getOrderNo() {
        return orderNo;
    }
    
    public void setOrderNo(Integer orderNo) {
        this.orderNo = orderNo;
    }
    
    public String getMenuId() {
        return menuId;
    }
    
    public void setMenuId(String menuId) {
        this.menuId = menuId;
    }
    
    public String getCreateBy() {
        return createBy;
    }
    
    public void setCreateBy(String createBy) {
        this.createBy = createBy;
    }
    
    public LocalDateTime getCreateTime() {
        return createTime;
    }
    
    public void setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
    }
    
    public String getUpdateBy() {
        return updateBy;
    }
    
    public void setUpdateBy(String updateBy) {
        this.updateBy = updateBy;
    }
    
    public LocalDateTime getUpdateTime() {
        return updateTime;
    }
    
    public void setUpdateTime(LocalDateTime updateTime) {
        this.updateTime = updateTime;
    }
    
    public PermissionDTO getParentPermission() {
        return parentPermission;
    }
    
    public void setParentPermission(PermissionDTO parentPermission) {
        this.parentPermission = parentPermission;
    }
    
    public List<PermissionDTO> getChildPermissions() {
        return childPermissions;
    }
    
    public void setChildPermissions(List<PermissionDTO> childPermissions) {
        this.childPermissions = childPermissions;
    }
    
    public Integer getRoleCount() {
        return roleCount;
    }
    
    public void setRoleCount(Integer roleCount) {
        this.roleCount = roleCount;
    }
    
    public Integer getUserCount() {
        return userCount;
    }
    
    public void setUserCount(Integer userCount) {
        this.userCount = userCount;
    }
    
    // ==================== 转换方法 ====================
    
    /**
     * 从Permission实体转换为PermissionDTO
     * 
     * @param permission Permission实体
     * @return PermissionDTO
     */
    public static PermissionDTO fromEntity(com.kexio.user.entity.Permission permission) {
        if (permission == null) {
            return null;
        }
        
        PermissionDTO dto = new PermissionDTO();
        dto.permissionId =permission.getId(); // Permission ID是String，需要转换
        dto.tenantId = permission.getTenantId();
        dto.permissionCode = permission.getCode();
        dto.permissionName = permission.getName();
        dto.permissionType = permission.getType();
        dto.description = permission.getDescription();
        dto.parentPermissionId = permission.getParentId();
        dto.permissionPath = permission.getPath();
        dto.status = permission.getStatus();
        dto.orderNo = permission.getOrderNo();
        dto.menuId = permission.getMenuId();  // 新架构中的菜单ID映射
        dto.createTime = permission.getCreateTime();
        dto.updateTime = permission.getUpdateTime();
        dto.createBy = permission.getCreateBy();
        dto.updateBy = permission.getUpdateBy();
        
        return dto;
    }
    
    /**
     * 转换为Permission实体（用于创建和更新）
     * 
     * @return Permission实体
     */
    public com.kexio.user.entity.Permission toEntity() {
        com.kexio.user.entity.Permission permission = new com.kexio.user.entity.Permission();
        
        if (this.permissionId != null) {
            permission.setId(String.valueOf(this.permissionId));
        }
        permission.setTenantId(this.tenantId);
        permission.setCode(this.permissionCode);
        permission.setName(this.permissionName);
        permission.setType(this.permissionType);
        permission.setDescription(this.description);
        permission.setParentId(this.parentPermissionId);
        permission.setPath(this.permissionPath);
        permission.setStatus(this.status);
        permission.setOrderNo(this.orderNo);
        permission.setMenuId(this.menuId);  // 新架构中的菜单ID映射
        permission.setCreateBy(this.createBy);
        permission.setCreateTime(this.createTime);
        permission.setUpdateBy(this.updateBy);
        permission.setUpdateTime(this.updateTime);
        
        return permission;
    }
    
    
    /**
     * 清除用于创建的ID字段
     */
    public void clearIdsForCreate() {
        this.permissionId = null;
        this.createTime = null;
        this.updateTime = null;
        this.createBy = null;
        this.updateBy = null;
    }
    
    // ==================== 验证方法 ====================
    
    /**
     * 验证DTO数据的有效性
     * 
     * @throws IllegalArgumentException 如果数据无效
     */
    public void validate() {
        // 基础字段验证
        if (!StringUtils.hasText(this.permissionCode)) {
            throw new IllegalArgumentException("权限编码不能为空");
        }
        
        if (!StringUtils.hasText(this.permissionName)) {
            throw new IllegalArgumentException("权限名称不能为空");
        }
        
        if (!StringUtils.hasText(this.permissionType)) {
            throw new IllegalArgumentException("权限类型不能为空");
        }
        
        if (this.status == null) {
            throw new IllegalArgumentException("状态不能为空");
        }
        
        // 清理字符串字段
        this.permissionCode = this.permissionCode.trim();
        this.permissionName = this.permissionName.trim();
        this.permissionType = this.permissionType.trim().toUpperCase();
        
        if (this.description != null) {
            this.description = this.description.trim();
            if (this.description.isEmpty()) {
                this.description = null;
            }
        }
        
        if (this.permissionPath != null) {
            this.permissionPath = this.permissionPath.trim();
            if (this.permissionPath.isEmpty()) {
                this.permissionPath = null;
            }
        }
    }
    
    /**
     * 检查是否有任何更新字段（用于更新操作）
     * 
     * @return true-有更新字段，false-无更新字段
     */
    public boolean hasAnyUpdateFields() {
        return (this.permissionName != null && !this.permissionName.isEmpty())
            || (this.permissionType != null && !this.permissionType.isEmpty())
            || (this.description != null && !this.description.isEmpty())
            || (this.parentPermissionId != null && !this.parentPermissionId.isEmpty())
            || (this.permissionPath != null && !this.permissionPath.isEmpty())
            || this.status != null
            || this.orderNo != null;
    }
    
    
    // ==================== 便捷方法 ====================
    
    /**
     * 检查是否为启用状态
     * 
     * @return true-启用，false-禁用或未设置
     */
    public boolean isEnabled() {
        return Integer.valueOf(1).equals(this.status);
    }
    
    /**
     * 设置为启用状态
     */
    public void setEnabled() {
        this.status = 1;
    }
    
    /**
     * 设置为禁用状态
     */
    public void setDisabled() {
        this.status = 0;
    }
    
    /**
     * 检查是否为根权限（没有父权限）
     * 
     * @return true-根权限，false-子权限
     */
    public boolean isRootPermission() {
        return this.parentPermissionId == null;
    }
    
    /**
     * 检查权限类型是否为操作权限
     * 
     * @return true-操作权限，false-其他类型
     */
    public boolean isOperationPermission() {
        return "OP".equals(this.permissionType);
    }
    
    /**
     * 检查权限类型是否为资源权限
     * 
     * @return true-资源权限，false-其他类型
     */
    public boolean isResourcePermission() {
        return "RESOURCE".equals(this.permissionType);
    }
    
    /**
     * 检查权限类型是否为API权限
     * 
     * @return true-API权限，false-其他类型
     */
    public boolean isApiPermission() {
        return "API".equals(this.permissionType);
    }
    
    @Override
    public String toString() {
        return "PermissionDTO{" +
                "permissionId=" + permissionId +
                ", tenantId='" + tenantId + '\'' +
                ", permissionCode='" + permissionCode + '\'' +
                ", permissionName='" + permissionName + '\'' +
                ", permissionType='" + permissionType + '\'' +
                ", parentPermissionId=" + parentPermissionId +
                ", status=" + status +
                ", orderNo=" + orderNo +
                '}';
    }
}
